package pe.cliente.proyecto.core.daobase.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import pe.adra.core.bean.FiltroEntidad;
import pe.adra.core.bean.SuportEntidad;
import pe.adra.core.dao.ext.DAOBaseImpl;
import pe.adra.core.dao.ext.QueryUtil;
import pe.adra.util.constantes.ConstantesUtil;
import pe.adra.util.exception.DAOException;
import pe.adra.util.text.Util;
import pe.adra.util.validate.ValidateUtil;
import pe.cliente.proyecto.core.daobase.AsientoDAOBase;
import pe.cliente.proyecto.dominio.Asiento;
import pe.cliente.proyecto.dominio.Estadio;

public class AsientoDAOBaseImpl extends DAOBaseImpl<Asiento> implements AsientoDAOBase {

	private static final Logger logger = LoggerFactory.getLogger(AsientoDAOBaseImpl.class);
	private EntityManager entityManager = null;
	private Query qy = null;

	public AsientoDAOBaseImpl(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	public int countListaAsiento(FiltroEntidad filtro) throws DAOException {
		return QueryUtil.count(this, filtro, SQL_QUERY_COUNT, qy).intValue();
	}

	public List<Asiento> getListaAsiento(FiltroEntidad filtro) throws DAOException {
		return QueryUtil.getLista(this, filtro, SQL_QUERY, qy);
	}

	public List<Asiento> getAsientoPorId(FiltroEntidad filtro) throws DAOException {
		return QueryUtil.getLista(this, filtro, SQL_QUERY_ID, qy);
	}

	public List<Asiento> getAsientoPorIdPorNumero(FiltroEntidad filtro) throws DAOException {
		return QueryUtil.getLista(this, filtro, SQL_QUERY_ID_NUMERO, qy);
	}

	public List<Asiento> getCboAsiento() throws DAOException {
		FiltroEntidad ent = new FiltroEntidad();
		Asiento filt = new Asiento();
		filt.setActivo(true);
		ent.setFiltro(filt);
		return QueryUtil.getCbo(this, ent, SQL_QUERY_CBO, qy, CAMPO_NUMERO);
	}

	public List<Asiento> getCboAsiento(FiltroEntidad filtro) throws DAOException {
		return QueryUtil.getCbo(this, filtro, SQL_QUERY_CBO, qy, CAMPO_NUMERO);
	}

	public List<Asiento> getAsientoPorID(Integer[] ids, String tipo) throws DAOException {
		FiltroEntidad ent = new FiltroEntidad();
		Asiento filt = new Asiento();
		filt.setActivo(true);
		ent.setFiltro(filt);
		return QueryUtil.getPorID(this, ent, SQL_QUERY_CBO, SQL_QUERY, qy, CAMPO_NUMERO, ids, tipo);
	}

	private void setValues(Asiento filtro, StringBuffer strbfSqlQuery, SuportEntidad... innerjoin) {
		QueryUtil.establecerCondicionInnerJoins(strbfSqlQuery, innerjoin);
		Util.quitarUltimoAND(strbfSqlQuery, QueryUtil.SQL_AND);
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_ID + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_ID), filtro.getId());
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_NUMERO + QueryUtil.SQL_LIKE + QueryUtil.SQL_FILTRO + CAMPO_NUMERO), filtro.getNumero());
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_TRIBUNA + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_TRIBUNA), filtro.getTribuna());
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + ESTADIO_CAMPO_ESTADIO + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + ESTADIO_CAMPO_ESTADIO), (ValidateUtil.isNotNull(filtro.getEstadio()) ? filtro.getEstadio().getId()
				: null));
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_ACTIVO + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_ACTIVO), filtro.getActivo());
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_CODIGOUSUARIO + QueryUtil.SQL_LIKE + QueryUtil.SQL_FILTRO + CAMPO_CODIGOUSUARIO), filtro.getCodigoUsuario());
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_FECHAREGISTRO + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_FECHAREGISTRO), filtro.getFechaRegistro());
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_CODIGOUSUARIOACTULIZAR + QueryUtil.SQL_LIKE + QueryUtil.SQL_FILTRO + CAMPO_CODIGOUSUARIOACTULIZAR), filtro.getCodigoUsuarioActulizar());
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_FECHAACTUALIZADA + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_FECHAACTUALIZADA), filtro.getFechaActualizada());
		Util.quitarUltimoAND(strbfSqlQuery, QueryUtil.SQL_AND);
		// if (logger.isDebugEnabled()) {
		logger.debug("strbfSqlQuery:" + strbfSqlQuery.toString());
		// }
	}

	private void setFiltroEntidad(Asiento filtro, SuportEntidad... innerjoin) {
		QueryUtil.establecerInnerJoinsParam(qy, innerjoin);
		QueryUtil.establecerParam(qy, CAMPO_ID, filtro.getId());
		QueryUtil.establecerParam(qy, CAMPO_NUMERO, filtro.getNumero(), true, true);
		QueryUtil.establecerParam(qy, CAMPO_TRIBUNA, filtro.getTribuna());
		QueryUtil.establecerParam(qy, ESTADIO_CAMPO_ESTADIO, (ValidateUtil.isNotNull(filtro.getEstadio()) ? (ValidateUtil.isNotNull(filtro.getEstadio().getId())?filtro.getEstadio():null) : null));
		QueryUtil.establecerParam(qy, CAMPO_ACTIVO, filtro.getActivo());
		QueryUtil.establecerParam(qy, CAMPO_CODIGOUSUARIO, filtro.getCodigoUsuario(), true, true);
		QueryUtil.establecerParam(qy, CAMPO_FECHAREGISTRO, filtro.getFechaRegistro());
		QueryUtil.establecerParam(qy, CAMPO_CODIGOUSUARIOACTULIZAR, filtro.getCodigoUsuarioActulizar(), true, true);
		QueryUtil.establecerParam(qy, CAMPO_FECHAACTUALIZADA, filtro.getFechaActualizada());
		// if (logger.isDebugEnabled()) {
		QueryUtil.printParameterQuery(qy);
		// }
	}

	protected Query procesarConsulta(Asiento filtro, StringBuffer strbfSqlQuery, SuportEntidad... innerjoin) {
		procesarConsulta(filtro, null, null, strbfSqlQuery, innerjoin);
		return qy;
	}

	protected Query procesarConsulta(Asiento filtro, Date finit, Date ffin, StringBuffer strbfSqlQuery, SuportEntidad... innerjoin) {
		if (ValidateUtil.isNotNull(filtro)) {
			if (ValidateUtil.isNotNull(finit) || ValidateUtil.isNotNull(ffin)) {
				setValues(filtro, finit, ffin, strbfSqlQuery, innerjoin);
				qy = getEntityManager().createQuery(strbfSqlQuery.toString());
				setFiltroEntidad(filtro, finit, ffin, innerjoin);
			} else {
				setValues(filtro, strbfSqlQuery, innerjoin);
				qy = getEntityManager().createQuery(strbfSqlQuery.toString());
				setFiltroEntidad(filtro, innerjoin);
			}
		}
		if (logger.isDebugEnabled()) {
			logger.debug("strbfSqlQuery:" + strbfSqlQuery.toString());
		}
		return qy;
	}

	protected Query procesarConsulta(Asiento objEntidad, Integer[] ids, StringBuffer strbfSqlQuery, SuportEntidad... innerjoin) {
		setValues(objEntidad, ids, strbfSqlQuery, innerjoin);
		qy = getEntityManager().createQuery(strbfSqlQuery.toString());
		setFiltroEntidad(objEntidad, ids, innerjoin);
		return qy;
	}

	protected void setValues(Asiento objEntidad, Integer[] ids, StringBuffer strbfSqlQuery, SuportEntidad... innerjoin) {
		setValues(objEntidad, strbfSqlQuery, innerjoin);
		QueryUtil.establecerCondicionIN(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_ID + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_ID), Arrays.asList(ids));
	}

	protected void setValues(Asiento filtro, Date finit, Date ffin, StringBuffer strbfSqlQuery, SuportEntidad... innerjoin) {
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_FECHAREGISTRO + QueryUtil.SQL_MENOS + QueryUtil.SQL_FILTRO + CAMPO_FECHAREGISTRO + QueryUtil.TOKEMN1), finit);
		QueryUtil.establecerCondicion(strbfSqlQuery, (QueryUtil.SQL_SEA + CAMPO_FECHAREGISTRO + QueryUtil.SQL_MAS + QueryUtil.SQL_FILTRO + CAMPO_FECHAREGISTRO + QueryUtil.TOKEMN2), ffin);
		setValues(filtro, strbfSqlQuery, innerjoin);
	}

	protected void setFiltroEntidad(Asiento filtro, Date finit, Date ffin, SuportEntidad... innerjoin) {
		QueryUtil.establecerParam(qy, CAMPO_FECHAREGISTRO + QueryUtil.TOKEMN1, finit);
		QueryUtil.establecerParam(qy, CAMPO_FECHAREGISTRO + QueryUtil.TOKEMN2, ffin);
		setFiltroEntidad(filtro, innerjoin);
	}

	protected void setFiltroEntidad(Asiento objEntidad, Integer[] ids, SuportEntidad... innerjoin) {
		QueryUtil.establecerParamIN(qy, CAMPO_ID, Arrays.asList(ids));
		setFiltroEntidad(objEntidad, innerjoin);
	}

	public AsientoDAOBaseUtil setQuery() {
		return new AsientoDAOBaseUtil();
	}

	public class AsientoDAOBaseUtil {

		private StringBuffer strBuffer;
		private Asiento filtro;
		private Query query = null;
		private Date frinit = null;
		private Date frfin = null;
		private Date fainit = null;
		private Date fafin = null;

		private void createBuffer() {
			if (ValidateUtil.isNull(strBuffer)) {
				strBuffer = new StringBuffer();
				strBuffer.append(SQL_QUERY);
				filtro = new Asiento();
			}

		}

		public AsientoDAOBaseUtil setId(Long id) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_ID + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_ID), id);
			filtro.setId(id);
			return this;
		}

		public AsientoDAOBaseUtil setNumero(String numero) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_NUMERO + QueryUtil.SQL_LIKE + QueryUtil.SQL_FILTRO + CAMPO_NUMERO), numero);
			filtro.setNumero(numero);
			return this;
		}

		public AsientoDAOBaseUtil setTribuna(int tribuna) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_TRIBUNA + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_TRIBUNA), tribuna);
			filtro.setTribuna(tribuna);
			return this;
		}

		public AsientoDAOBaseUtil setEstadio(Estadio estadio) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + ESTADIO_CAMPO_ESTADIO + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + ESTADIO_CAMPO_ESTADIO), estadio);
			filtro.setEstadio(estadio);
			return this;
		}

		public AsientoDAOBaseUtil setActivo(Boolean activo) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_ACTIVO + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_ACTIVO), activo);
			filtro.setActivo(activo);
			return this;
		}

		public AsientoDAOBaseUtil setCodigoUsuario(String codigoUsuario) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_CODIGOUSUARIO + QueryUtil.SQL_LIKE + QueryUtil.SQL_FILTRO + CAMPO_CODIGOUSUARIO), codigoUsuario);
			filtro.setCodigoUsuario(codigoUsuario);
			return this;
		}

		public AsientoDAOBaseUtil setFechaRegistro(Date fechaRegistro) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_FECHAREGISTRO + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_FECHAREGISTRO), fechaRegistro);
			filtro.setFechaRegistro(fechaRegistro);
			return this;
		}

		public AsientoDAOBaseUtil setCodigoUsuarioActulizar(String codigoUsuarioActulizar) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_CODIGOUSUARIOACTULIZAR + QueryUtil.SQL_LIKE + QueryUtil.SQL_FILTRO + CAMPO_CODIGOUSUARIOACTULIZAR), codigoUsuarioActulizar);
			filtro.setCodigoUsuarioActulizar(codigoUsuarioActulizar);
			return this;
		}

		public AsientoDAOBaseUtil setFechaActualizada(Date fechaActualizada) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_FECHAACTUALIZADA + QueryUtil.SQL_EQ + QueryUtil.SQL_FILTRO + CAMPO_FECHAACTUALIZADA), fechaActualizada);
			filtro.setFechaActualizada(fechaActualizada);
			return this;
		}

		private void setFiltros() {
			Util.quitarUltimoAND(strBuffer, QueryUtil.SQL_AND);
			if (logger.isDebugEnabled()) {
				logger.debug("strBuffer:" + strBuffer.toString());
			}
			query = entityManager.createQuery(strBuffer.toString());
			QueryUtil.establecerParam(query, CAMPO_ID, filtro.getId());
			QueryUtil.establecerParam(query, CAMPO_NUMERO, filtro.getNumero(), true, true);
			QueryUtil.establecerParam(query, CAMPO_TRIBUNA, filtro.getTribuna());
			QueryUtil.establecerParam(query, ESTADIO_CAMPO_ESTADIO, filtro.getEstadio());
			QueryUtil.establecerParam(query, CAMPO_ACTIVO, filtro.getActivo());
			QueryUtil.establecerParam(query, CAMPO_CODIGOUSUARIO, filtro.getCodigoUsuario(), true, true);
			QueryUtil.establecerParam(query, CAMPO_FECHAREGISTRO, filtro.getFechaRegistro());
			QueryUtil.establecerParam(query, CAMPO_CODIGOUSUARIOACTULIZAR, filtro.getCodigoUsuarioActulizar(), true, true);
			QueryUtil.establecerParam(query, CAMPO_FECHAACTUALIZADA, filtro.getFechaActualizada());
			QueryUtil.establecerParam(query, CAMPO_FECHAREGISTRO + QueryUtil.TOKEMN1, frinit);
			QueryUtil.establecerParam(query, CAMPO_FECHAREGISTRO + QueryUtil.TOKEMN2, frfin);
			QueryUtil.establecerParam(query, CAMPO_FECHAACTUALIZADA + QueryUtil.TOKEMN1, fainit);
			QueryUtil.establecerParam(query, CAMPO_FECHAACTUALIZADA + QueryUtil.TOKEMN2, fafin);

			if (logger.isDebugEnabled()) {
				QueryUtil.printParameterQuery(query);
			}
		}

		public AsientoDAOBaseUtil setFechaRegistro(Date finit, Date ffin) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_FECHAREGISTRO + QueryUtil.SQL_MENOS + QueryUtil.SQL_FILTRO + CAMPO_FECHAREGISTRO + QueryUtil.TOKEMN1), finit);
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_FECHAREGISTRO + QueryUtil.SQL_MAS + QueryUtil.SQL_FILTRO + CAMPO_FECHAREGISTRO + QueryUtil.TOKEMN2), ffin);
			this.frinit = finit;
			this.frfin = ffin;
			return this;
		}

		public AsientoDAOBaseUtil setFechaActualizada(Date finit, Date ffin) {
			createBuffer();
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_FECHAACTUALIZADA + QueryUtil.SQL_MENOS + QueryUtil.SQL_FILTRO + CAMPO_FECHAACTUALIZADA + QueryUtil.TOKEMN1), finit);
			QueryUtil.establecerCondicion(strBuffer, (QueryUtil.SQL_SEA + CAMPO_FECHAACTUALIZADA + QueryUtil.SQL_MAS + QueryUtil.SQL_FILTRO + CAMPO_FECHAACTUALIZADA + QueryUtil.TOKEMN2), ffin);
			this.fainit = finit;
			this.fafin = ffin;
			return this;
		}

		@SuppressWarnings("unchecked")
		public List<Asiento> ejecutaFiltroFilas() throws DAOException {
			setFiltros();
			return query.getResultList();
		}

		@SuppressWarnings("unchecked")
		public List<Asiento> ejecutaFiltroFilas(int inicio, int fin, String strSort, String strOrder) throws DAOException {
			setFiltros();
			if ((inicio > -ConstantesUtil.NUMBER_0) && (fin > -ConstantesUtil.NUMBER_0)) {
				query.setFirstResult(inicio);
				query.setMaxResults(fin);
			}
			if (ValidateUtil.isNotNull(strSort) && ValidateUtil.isNotNull(strOrder)) {
				QueryUtil.setOrder(strBuffer, strSort, strOrder);
			}
			return query.getResultList();
		}

		public Asiento ejecutaFiltroPrimeraFila() throws DAOException {
			setFiltros();
			query.setFirstResult(1);
			query.setMaxResults(1);
			return (Asiento) query.getSingleResult();
		}
	}

	private EntityManager getEntityManager() {
		return entityManager;
	}

}
